package com.qisimanxiang.dalaran.zuul.sentinel;

import com.alibaba.csp.sentinel.slots.block.RuleConstant;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRule;
import com.alibaba.csp.sentinel.slots.block.degrade.DegradeRuleManager;
import com.qisimanxiang.dalaran.zuul.config.SentinelConfig;
import com.qisimanxiang.dalaran.zuul.rule.CustomerDegradeRule;
import com.qisimanxiang.dalaran.zuul.util.CommonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Collections;


/**
 * @author wangmeng
 * @date created in 1:42 下午 2019/9/16
 * @modified by
 */
@Slf4j
@Component
public class DegradeStrategy {

    public static final int DEGRADE_RT = 100;
    //单位秒
    public static final int DEGRADE_MAX_TIME_WINDOW = 1000;
    public static final int DEGRADE_MIN_TIME_WINDOW = 10;
    public static final String RESOURCE_NAME_CUSTOMER_DEGRADE_SERVICE = "customer-service-degrade";

    private static DegradeStrategy instance;
    private SentinelConfig sentinelConfig;

    public DegradeStrategy() {
        instance = this;
    }

    public static void flush(SentinelConfig config) {
        log.info("refresh qps limit: {}", config);
        instance.sentinelConfig = config;
        instance.flushDegrade();
    }

    private void flushDegrade() {
        DegradeRuleManager.loadRules(Collections.singletonList(customerServiceDegrade()));
    }

    /**
     * 客户&服务级别熔断
     *
     * @return
     */
    private DegradeRule customerServiceDegrade() {
        CustomerDegradeRule flowRule = new CustomerDegradeRule(RESOURCE_NAME_CUSTOMER_DEGRADE_SERVICE);
        flowRule.setCount(CommonUtils.firstNotNull(sentinelConfig.getGlobalDegradeRT(), DEGRADE_RT));
        flowRule.setGrade(RuleConstant.DEGRADE_GRADE_RT);
        flowRule.setMinTimeWindow(CommonUtils.firstNotNull(sentinelConfig.getGlobalMinDegradeTimeWindow(), DEGRADE_MIN_TIME_WINDOW));
        flowRule.setTimeWindow(CommonUtils.firstNotNull(sentinelConfig.getGlobalMaxDegradeTimeWindow(), DEGRADE_MAX_TIME_WINDOW));
        return flowRule;
    }
}
